home *** CD-ROM | disk | FTP | other *** search
- /* popen(): open a file handle to a process. Works only under MiNT.
- * Written by Eric R. Smith, based on the TOS version by Kai-Uwe Bloem.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <fcntl.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #ifdef __TURBOC__
- #include <sys\types.h>
- #else
- #include <sys/types.h>
- #endif
- #include <wait.h>
- #include <mintbind.h>
-
- struct _pipe {
- int pid; /* process id of child */
- FILE *pfile; /* created file descriptor */
- struct _pipe *pnext; /* next pipe in the list. */
- };
-
- static struct _pipe *__pipes = NULL; /* head of pipe list */
-
- FILE *popen(command, type)
- const char *command, *type;
- {
- struct _pipe *p; /* the new pipe's list entry */
- short pipfd[2]; /* pipe file handles */
- int savefd; /* saved file descriptor for parent */
- int kidfd; /* file descriptor changed in child */
- /* 1 for "r", 0 for "w" */
-
- char *shell;
- FILE *pipefile = 0;
- extern int __mint;
- long r;
-
- if (__mint == 0) {
- errno = EINVAL;
- return (FILE *)0;
- }
-
- shell = getenv("SHELL");
- if (!shell)
- shell = "sh";
-
- /* get space for the new pipe. If we can't get it then that's that */
- p = (struct _pipe *) malloc(sizeof(struct _pipe));
- if (p == NULL) return (FILE *)0;
-
- /* initialize the new pipe entry */
- kidfd = (*type == 'r') ? 1 : 0;
-
- r = Fdup (kidfd);
- savefd = (int) r;
- /* get those close-on-exec flags right...
- (well just do fork/exec would be easier :-) -nox */
-
- if (r < 0 || (r = Fcntl (savefd, 1L, F_SETFD)) < 0 ||
- (r = Fpipe(pipfd)) < 0) { /* can't create pipe?? */
- free(p);
- errno = (int) -r;
- return (FILE *)0;
- }
-
- /* other side of the pipe should be closed in the child */
- (void) Fcntl(pipfd[1 - kidfd], (long) 1, F_SETFD);
- Fforce(kidfd, pipfd[kidfd]);
- Fclose(pipfd[kidfd]);
- p->pid = spawnlp(P_NOWAIT, shell, shell, "-c", command, (char *)0);
- Fforce(kidfd, savefd);
- Fclose(savefd);
-
- if (p->pid > 0) { /* command ran all right */
- /* note: 1-kidfd tells us which handle to use in the parent */
- pipefile = fdopen(pipfd[1 - kidfd], type);
- }
-
- if (pipefile) {
- p->pfile = pipefile;
- p->pnext = __pipes;
- __pipes = p;
- }
- else {
- /* carefully release all resources */
- Fclose (pipfd[1 - kidfd]);
- if (p->pid > 0) /* just in case... */
- waitpid (p->pid, (int *) NULL, 0);
- free(p);
- }
- return pipefile;
- }
-
- /* close a pipe created by popen().
- */
- int pclose(fp)
- FILE *fp;
- {
- struct _pipe *p, /* the pipe's list element */
- **q; /* predecessor of p in the list */
- int status = -1; /* return status of the command */
-
- /* search the pipe list for a pipe matching the FILE descriptor */
- for (p = __pipes, q = &__pipes; p && p->pfile != fp;
- q = &p->pnext, p = p->pnext);
- if (p == NULL) /* Never had a popen() for this file... */
- return status; /* this pclose call makes no sense ! */
-
- fclose(p->pfile); /* close the connection */
-
- /* now wait for the command to finish */
- waitpid (p->pid, &status, 0);
-
- /* remove the pipe from the list */
- *q = p->pnext;
-
- /* Now free the pipe entry */
- free(p);
-
- return status;
- }
-